package consumer

import (
	"context"
	"errors"
	"fmt"
	"time"

	jsoniter "github.com/json-iterator/go"
	"github.com/nsqio/go-nsq"
	"zhonghui/console/service"
	"zhonghui/console/structs"
	"zhonghui/console/warehouse/cfgx"
	"zhonghui/console/warehouse/dbx/db_zh_kernel"
	"zhonghui/console/warehouse/helperx"
	"zhonghui/console/warehouse/logx"
	"zhonghui/console/warehouse/modelx/model_zh_kernel"
)

// SmsSendConsumer 处理信息发送
type SmsSendConsumer struct{}

func (h *SmsSendConsumer) GetTopicName() string {
	return cfgx.Cfg().GetString("console.topics.sms_send")
}

func (h *SmsSendConsumer) GetQueueName() string {
	return cfgx.Cfg().GetString("console.channels.sms_send")
}

func (h *SmsSendConsumer) HandleMessage(m *nsq.Message) error {
	defer func() {
		if r := recover(); r != nil {
			logx.Zap().Errorw("消费者异常", "err", errors.New(fmt.Sprintf("%s", r)))
		}
	}()

	ctx := helperx.MakeCtxWithRequestId()

	msgId := fmt.Sprintf("%s", m.ID)

	// logx.ZapTrace(ctx).Infow("开始处理消息", "queue_name", h.GetQueueName(), "msg_id", msgId, "msg_body", string(m.Body))

	body := structs.SmsSendWorkerBody{}
	if err := jsoniter.Unmarshal(m.Body, &body); err != nil {
		logx.ZapTrace(ctx).Errorw("解析通知结构失败，忽略", "queue_name", h.GetQueueName(), "msg_id", msgId, "err", err)
		return nil
	}

	// 查询，简单去重
	record := model_zh_kernel.SysSmsRecord{}
	if err := db_zh_kernel.ClientCtx(ctx).Where("id = ?", body.RecordID).Take(&record).Error; err != nil {
		return nil
	}

	// 如果状态不是queue
	if record.Status != "queue" {
		// 等会再试
		if record.Status == "" {
			m.Requeue(time.Second * 10)
			return nil
		}
		// 其他状态，忽略
		return nil
	}

	// 查询任务
	task := model_zh_kernel.SysTask{}
	if err := db_zh_kernel.ClientCtx(ctx).Where("id = ?", body.TaskID).Take(&task).Error; err != nil {
		return err
	}

	// 如果任务是暂停状态，则延迟30秒再尝试
	if task.Status == structs.TaskStatusPaused {
		m.Requeue(time.Second * 60)
		return nil
	}

	// 如果任务是非进行状态，则忽略
	if task.Status == structs.TaskStatusStopped || task.Status == structs.TaskStatusCompleted {
		return nil
	}

	// 再次去重，改状态
	up := db_zh_kernel.ClientCtx(ctx).Model(model_zh_kernel.SysSmsRecord{}).Where("id = ? and status = 'queue'", record.ID).Updates(map[string]interface{}{
		"status": "prepared",
	})
	if up.Error != nil {
		return nil
	}
	if up.RowsAffected != 1 {
		return nil
	}

	// logx.ZapTrace(ctx).Infow("准备发送短信", "record", record)

	// 解析短信模板参数
	params := service.ParseRecordParamsForSms(&record)

	// 发送短信
	if err := service.SendSms(record.Phone, params, true, task.SmsTemplate); err != nil {
		h.fail(ctx, &record, "")
		return nil
	}

	// 发送完毕保存结果
	up = db_zh_kernel.ClientCtx(ctx).Model(model_zh_kernel.SysSmsRecord{}).Where("id = ? and status = 'prepared'", record.ID).Updates(map[string]interface{}{
		"status": msgId,
	})
	if up.Error != nil {
		return nil
	}
	if up.RowsAffected != 1 {
		return nil
	}

	service.ReportData(record.TaskID, record.Phone, structs.ReportKindSmsSend, "")

	service.AddTaskTempProgress(record.TaskID)

	return nil
}

func (h *SmsSendConsumer) fail(ctx context.Context, record *model_zh_kernel.SysSmsRecord, extra string) {
	db_zh_kernel.ClientCtx(ctx).Model(model_zh_kernel.SysSmsRecord{}).Where("id = ? and status in ('queue', 'prepared')", record.ID).Updates(map[string]interface{}{
		"status": "fail",
	})
	service.AddTaskTempProgressFail(record.TaskID)
	service.ReportData(record.TaskID, record.Phone, structs.ReportKindSmsFail, extra)
}
